{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Frequently Asked Questions (FAQ)\n",
    "\n",
    "`Linux` `CPU` `全流程` `初级` `中级` `高级`\n",
    "\n",
    "[![](https://gitee.com/mindspore/docs/raw/master/resource/_static/logo_source.png)](https://gitee.com/mindspore/mindquantum/blob/master/tutorials/0.frequently_asked_questions.ipynb) [![](https://gitee.com/mindspore/mindquantum/raw/master/tutorials/images/view_mindquantum_api.png)](https://mindspore.cn/mindquantum/docs/zh-CN/master/mindquantum.core.html)\n",
    "\n",
    "## 1. 为什么量子模拟器的运算速度很慢？\n",
    "\n",
    "量子模拟器运算速度很慢的原因可能是设置的并行内核数太低了或者是并行内核数过高，特别是在大型服务器中，如果不设置内核数，默认会占用所有的CPU，速度反而会降低。\n",
    "\n",
    "在运行代码前，我们需要设置量子模拟器运行时的并行内核数，例如：如果需要设置并行内核数为4，可运行如下代码：\n",
    "\n",
    "export OMP_NUM_THREADS=4\n",
    "\n",
    "当发现量子模拟器运算速度很慢的时候，可以适当调整并行内核数。\n",
    "\n",
    "请根据模型规模合理设置并行内核数以达到最优效果。\n",
    "\n",
    "## 2. 关于双量子比特门——`CNOT`是如何实现的？\n",
    "\n",
    "对于`CNOT`门，其本质上是受控`X`门（`Controlled-X` gate），因此在MindQuantum中，如果我们需要执行`CNOT`门，只需设定`X`门的控制比特位和目标比特位即可（实际上，任意的量子门我们都可以设定控制比特位和所需执行量子门操作的目标比特位）。例如运行如下代码：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "X(1 <-: 0)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindquantum import X\n",
    "\n",
    "X.on(1, 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行结果为：X(1 <-: 0) ，其表示第1位量子比特位为目标比特位，第0位量子比特位为控制比特位，第1位量子比特受第0位量子比特控制，若第0位量子比特为1，则对第1位量子比特执行`X`门操作，否则不作任何操作。\n",
    "\n",
    "为了更加直观，我们将其量子线路打印出来，运行如下代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space: pre;\"><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q0: ──●──</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">      │  </span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q1: ──X──</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "q0: ──●──\n",
       "      │  \n",
       "q1: ──X──"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindquantum import Circuit\n",
    "\n",
    "circuit = Circuit()\n",
    "circuit += X.on(1, 0)\n",
    "circuit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这就是MindQuantum中实现`CNOT`门的语法，大家需要注意。如打印线路错乱，请参考下面第四条，设置浏览器或者终端的等宽字体。\n",
    "\n",
    "## 3. 关于量子比特的读取顺序？\n",
    "\n",
    "在MindQuantum中，量子比特的读取顺序都是从右往左的。我们通过一个具体的例子来说明。\n",
    "\n",
    "首先，运行如下代码，得到一个3量子比特的均匀叠加态："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "√2/4¦000⟩\n",
      "√2/4¦001⟩\n",
      "√2/4¦010⟩\n",
      "√2/4¦011⟩\n",
      "√2/4¦100⟩\n",
      "√2/4¦101⟩\n",
      "√2/4¦110⟩\n",
      "√2/4¦111⟩\n"
     ]
    }
   ],
   "source": [
    "from mindquantum.simulator import Simulator\n",
    "from mindquantum import H, UN\n",
    "\n",
    "sim = Simulator('projectq', 3)\n",
    "\n",
    "circuit1 = Circuit()\n",
    "circuit1 += UN(H, 3)\n",
    "\n",
    "sim.apply_circuit(circuit1)\n",
    "print(sim.get_qs(True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从运行的结果可以看到，我们得到了3量子比特的均匀叠加态，需要说明的是，所呈现的量子态，最右位的表示是第0位量子比特，中间位表示第1位量子比特，最左位表示第2位量子比特。\n",
    "\n",
    "我们再举一个例子，运行如下代码，打印量子线路和此时的量子态："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "projectq simulator with 2 qubits.\n",
      "Current quantum state:\n",
      "1¦10⟩\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space: pre;\"><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q0: ─────</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">         </span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q1: ──X──</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "q0: ─────\n",
       "         \n",
       "q1: ──X──"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sim1 = Simulator('projectq', 2)\n",
    "\n",
    "circuit2 = Circuit()\n",
    "circuit2 += X.on(1)\n",
    "\n",
    "sim1.apply_circuit(circuit2)\n",
    "\n",
    "print(sim1)\n",
    "circuit2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到此时的量子态为$|10\\rangle$​​态，量子态中的数字1表示的是第1位量子比特为$|1\\rangle$​​，数字0表示的是第0位量子比特为$|0\\rangle$​​。我们简单地验证一下，在第1位量子比特添加测量门，运行如下代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space: pre;\"><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q0: ──────────────</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">                  </span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q1: ──X────</span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">M</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">(q1)──</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "q0: ──────────────\n",
       "                  \n",
       "q1: ──X────M(q1)──"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindquantum import Measure\n",
    "\n",
    "circuit2 += Measure('q1').on(1)\n",
    "circuit2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从打印的结果可以看到，我们已经在第1位量子比特上添加了测量门。从理论上讲，第1位的量子比特是$|1\\rangle$​​，所以测量的结果应该也是$|1\\rangle$​​​，我们运行如下代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space: pre;\"><span style=\"color: #808000; text-decoration-color: #808000\">shots: </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">Keys: q1│</span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.00</span><span style=\"color: #808000; text-decoration-color: #808000\">     </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.2</span><span style=\"color: #808000; text-decoration-color: #808000\">         </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.4</span><span style=\"color: #808000; text-decoration-color: #808000\">         </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.6</span><span style=\"color: #808000; text-decoration-color: #808000\">         </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.8</span><span style=\"color: #808000; text-decoration-color: #808000\">         </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.0</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">────────┼───────────┴───────────┴───────────┴───────────┴───────────┴</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">       </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span><span style=\"color: #808000; text-decoration-color: #808000\">│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">        │                                                            </span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'1'</span><span style=\"color: #808000; text-decoration-color: #808000\">: </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">100</span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">}</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "shots: 100\n",
       "Keys: q1│0.00     0.2         0.4         0.6         0.8         1.0\n",
       "────────┼───────────┴───────────┴───────────┴───────────┴───────────┴\n",
       "       1│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓\n",
       "        │                                                            \n",
       "{'1': 100}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sim1.reset()\n",
    "\n",
    "result = sim1.sampling(circuit2, shots=100)\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从运行的结果可以看到，对存在测量门的量子比特进行重复采样100次，得到的就是100次1的结果，所以再次验证$|10\\rangle$态中的$|1\\rangle$​是第1位量子比特。\n",
    "\n",
    "因此，在MindQuantum中，量子比特的读取顺序都是从右往左的。\n",
    "\n",
    "## 4. 若打印量子线路时出现线路错乱，该如何解决？\n",
    "\n",
    "我们可以在MindQuantum中搭建各种各样的量子线路，最后我们还可以将搭建好的量子线路打印出来。例如，我们运行如下代码来搭建量子线路："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space: pre;\"><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q0: ──H────●────</span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">RX</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">(π/</span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">)───────●───────</span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">M</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">(q0)──</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">           │                  │              </span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">q1: ───────X───────────────</span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">RY</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">(π/</span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">)────</span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">M</span><span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">(q1)──</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "q0: ──H────●────RX(π/4)───────●───────M(q0)──\n",
       "           │                  │              \n",
       "q1: ───────X───────────────RY(π/2)────M(q1)──"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from mindquantum import RX, RY\n",
    "\n",
    "circuit3 = Circuit()\n",
    "circuit3 += H.on(0)\n",
    "circuit3 += X.on(1, 0)\n",
    "circuit3 += RX(np.pi/4).on(0)\n",
    "circuit3 += RY(np.pi/2).on(1, 0)\n",
    "circuit3 += Measure('q0').on(0)\n",
    "circuit3 += Measure('q1').on(1)\n",
    "circuit3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是，有时会出现如下图所示的线路错乱问题。\n",
    "\n",
    "![](./images/error_circuit.png)\n",
    "\n",
    "这个时候，我们只需要打开浏览器的设置，找到“外观”，找到“自定义字体”，然后在“宽度固定的字体”（有的浏览器为“等宽字体”）下，选择“Consolas”字体即可。此外，用户还可以下载并安装开源的[Fira Code](https://github.com/tonsky/FiraCode)字体来获得更优质的输出。当我们设置好等宽字体后，就可以看到最开始打印的量子线路了。（如下网址提供了一些等宽字体供用户自行选择[https://zhuanlan.zhihu.com/p/116230037/](https://zhuanlan.zhihu.com/p/116230037/)）\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "d62cf896b9ca57de08105ce3983377439eacacf6f6599f9150bf400edf4fa4b8"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
